package org.example.mybatis.session;

import org.example.mybatis.executor.Executor;
import org.example.mybatis.executor.SimpleExecutor;
import org.example.mybatis.proxy.MapperProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * SqlSession默认实现类
 */
public class DefaultSqlSession implements SqlSession {
    private static final Logger logger = LoggerFactory.getLogger(DefaultSqlSession.class);

    private final Configuration configuration;
    private final Executor executor;
    private Connection connection;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
        this.connection = configuration.getConnection();
        this.executor = new SimpleExecutor(this.configuration);
    }

    @Override
    public <T> T selectOne(String statement, Object parameter) {
        List<T> list = this.selectList(statement, parameter);
        if (list.size() == 1) {
            return list.get(0);
        } else if (list.size() > 1) {
            throw new RuntimeException("查询结果期望是一条，但返回了多条记录");
        } else {
            return null;
        }
    }

    @Override
    public <E> List<E> selectList(String statement, Object parameter) {
        MappedStatement ms = configuration.getMappedStatement(statement);
        if (ms == null) {
            throw new RuntimeException("未找到对应的MappedStatement: " + statement);
        }
        return executor.query(ms, parameter);
    }

    @Override
    public int insert(String statement, Object parameter) {
        MappedStatement ms = configuration.getMappedStatement(statement);
        if (ms == null) {
            throw new RuntimeException("未找到对应的MappedStatement: " + statement);
        }
        return executor.update(ms, parameter);
    }

    @Override
    public int update(String statement, Object parameter) {
        MappedStatement ms = configuration.getMappedStatement(statement);
        if (ms == null) {
            throw new RuntimeException("未找到对应的MappedStatement: " + statement);
        }
        return executor.update(ms, parameter);
    }

    @Override
    public int delete(String statement, Object parameter) {
        MappedStatement ms = configuration.getMappedStatement(statement);
        if (ms == null) {
            throw new RuntimeException("未找到对应的MappedStatement: " + statement);
        }
        return executor.update(ms, parameter);
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getMapper(Class<T> type) {
        MapperProxy<T> mapperProxy = new MapperProxy<>(this, type);
        return (T) Proxy.newProxyInstance(
                type.getClassLoader(),
                new Class[]{type},
                mapperProxy);
    }

    @Override
    public void close() {
        if (connection != null) {
            try {
                connection.close();
                logger.info("数据库连接已关闭");
            } catch (SQLException e) {
                logger.error("关闭数据库连接出错", e);
            }
        }
    }

    public Configuration getConfiguration() {
        return configuration;
    }
}